package com.qigao.mall.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qigao.mall.api.AccountInfoService;
import com.qigao.mall.api.AccountSerivce;
import com.qigao.mall.api.WithDrawService;
import com.qigao.mall.commons.dto.*;
import com.qigao.mall.commons.enums.*;
import com.qigao.mall.commons.utils.DateUtil;
import com.qigao.mall.commons.utils.IDUtils;
import com.qigao.mall.jdbc.mapper.TbWithDrawInfoMapper;
import com.qigao.mall.jdbc.model.TbAccountInfo;
import com.qigao.mall.jdbc.model.TbWithDrawInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author luiz
 * @Title: com.qigao.mall.service.impl
 * @ProjectName three-mall
 * @date 2020-06-2020-06-12 11:01
 * @Description:
 */
@Service
@Slf4j
public class WithDrawServiceImpl implements WithDrawService {
    @Resource
    private TbWithDrawInfoMapper tbWithDrawInfoMapper;
    @Resource
    private AccountSerivce accountSerivce;
    @Resource
    private AccountInfoService accountInfoService;
    @Resource
    DataSourceTransactionManager transactionManager;

    @Override
    public Result applyWithDraw(WithDrawApplyDto withDrawApplyDto) {
        BigDecimal withDrawAmt=new BigDecimal(withDrawApplyDto.getWithDrawAmt());
        //1.检查余额
        Result checkResult=accountSerivce.checkBalance(withDrawApplyDto.getUserNo(),AccountTypeEnum.CASH_ACCOUNT.getCode(),withDrawAmt);
        if(!checkResult.isSuccess()){
            return checkResult;
        }
        TbAccountInfo tbAccountInfo=(TbAccountInfo)checkResult.getData();
        //2.记录
        //3.更新账户可用余额
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setName(TransactionTypeEnum.APPLY_WITHDRAW.getCode());
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        try {
            TbWithDrawInfo tbWithDrawInfo=new TbWithDrawInfo();
            String withdrawOrderNo=IDUtils.genIdStr(IdTypeEnum.WITHDRAW);
            tbWithDrawInfo.setWithdrawOrderNo(withdrawOrderNo);
            BeanUtils.copyProperties(tbAccountInfo,tbWithDrawInfo);
            tbWithDrawInfo.setId(null);
            tbWithDrawInfo.setApplyTime(new Date());
            tbWithDrawInfo.setWithdrawAmt(withDrawAmt);
            tbWithDrawInfo.setStatus(WithDrawStatusEnum.WITHDRAW_INIT.getCode());
            tbWithDrawInfo.setCreateNo(withDrawApplyDto.getUserNo());
            tbWithDrawInfo.setCreateTime(new Date());
            tbWithDrawInfo.setModiNo(withDrawApplyDto.getUserNo());
            tbWithDrawInfo.setModiTime(new Date());
            tbWithDrawInfoMapper.insertSelective(tbWithDrawInfo);
            AccountAmtOperDto accountOperDto=new AccountAmtOperDto();
            accountOperDto.setAccoutNo(tbWithDrawInfo.getAccountNo());
            accountOperDto.setSourceTradeType(TradeTypeEnum.WITHDRAW);
            accountOperDto.setTradeAmt(BigDecimal.ZERO.subtract(withDrawAmt));
            accountOperDto.setSourceOrderNo(withdrawOrderNo);
            accountSerivce.operAccountAmt(accountOperDto);
            transactionManager.commit(transactionStatus);
            log.info("对账号:{}进行提现申请:{}成功!",tbAccountInfo.getAccountNo(),withDrawAmt);
            return Result.newSuccess();
        } catch (Exception e) {
            log.error("提现申请发生异常,事务回滚:{}", e);
            transactionManager.rollback(transactionStatus);
            return Result.newError(ResultCode.SAVE_DB_ERROR);
        }
    }

    @Override
    public Result<PageInfo<WithDrawOrderResultDto>> findWithDrawPage(WithDrawQueryDto withDrawQueryDto) {
        PageHelper.startPage(withDrawQueryDto.getPageNum(),withDrawQueryDto.getPageSize());
        Page<TbWithDrawInfo> tbWithDrawInfoPage=(Page<TbWithDrawInfo>)tbWithDrawInfoMapper.selectWithDrawList(withDrawQueryDto);
        Page<WithDrawOrderResultDto> withDrawOrderResultDtoPage=new Page<WithDrawOrderResultDto>();
        BeanUtils.copyProperties(tbWithDrawInfoPage,withDrawOrderResultDtoPage);
        if(tbWithDrawInfoPage.getResult()!=null){
            for(TbWithDrawInfo tbWithDrawInfo:tbWithDrawInfoPage.getResult()){
                withDrawOrderResultDtoPage.add(convertToDto(tbWithDrawInfo));
            }
        }
        return Result.newSuccess(new PageInfo<>(withDrawOrderResultDtoPage));
    }

    @Override
    public List<WithDrawOrderResultDto> findOrderResultByCond(WithDrawQueryDto withDrawQueryDto) {
        List<TbWithDrawInfo> tbWithDrawInfos=(List<TbWithDrawInfo>)tbWithDrawInfoMapper.selectWithDrawList(withDrawQueryDto);
        List<WithDrawOrderResultDto> withDrawOrderResultDtos=new ArrayList<>();
        for(TbWithDrawInfo tbWithDrawInfo:tbWithDrawInfos){
            withDrawOrderResultDtos.add(convertToDto(tbWithDrawInfo));
        }
        return withDrawOrderResultDtos;
    }

    @Override
    public Result withDrawAudit(WithDrawAuditDto withDrawAuditDto) {
        for(String orderNo:withDrawAuditDto.getOrderNos()){
            withDrawAuditDto.setOrderNo(orderNo);
            Result singleResult=sigleAudit(withDrawAuditDto);
            if(!singleResult.isSuccess())return singleResult;
        }
        return Result.newSuccess();
    }

    private Result sigleAudit(WithDrawAuditDto withDrawAuditDto) {
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setName(TransactionTypeEnum.AUDIT_WITHDRAW.getCode());
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        try {
            TbWithDrawInfo tbWithDrawInfo=tbWithDrawInfoMapper.selectByOrderNo(withDrawAuditDto.getOrderNo());
            tbWithDrawInfo.setWithdrawOrderNo(withDrawAuditDto.getOrderNo());
            tbWithDrawInfo.setAuditTime(new Date());
            tbWithDrawInfo.setAuditNo(withDrawAuditDto.getUserNo());
            tbWithDrawInfo.setAuditMemo(withDrawAuditDto.getAuditDesc());
            tbWithDrawInfo.setModiNo(withDrawAuditDto.getUserNo());
            tbWithDrawInfo.setModiTime(new Date());
            if(AuditActionEnum.PASS.equals(withDrawAuditDto.getAuditActionEnum())){
                tbWithDrawInfo.setStatus(WithDrawStatusEnum.WITHDRAW_SUCCESS.getCode());
            } if(AuditActionEnum.REJECT.equals(withDrawAuditDto.getAuditActionEnum())){
                tbWithDrawInfo.setStatus(WithDrawStatusEnum.WITHDRAW_REJECT.getCode());
                AccountAmtOperDto accountOperDto=new AccountAmtOperDto();
                accountOperDto.setAccoutNo(withDrawAuditDto.getUserNo());
                accountOperDto.setSourceTradeType(TradeTypeEnum.WITHDRAW_BACK);
                accountOperDto.setTradeAmt(tbWithDrawInfo.getWithdrawAmt());
                accountOperDto.setSourceOrderNo(withDrawAuditDto.getOrderNo());
                accountSerivce.operAccountAmt(accountOperDto);
            }
            tbWithDrawInfoMapper.updateByPrimaryKeySelective(tbWithDrawInfo);
            transactionManager.commit(transactionStatus);
            log.info("对提现订单号:{}进行提现审核成功!",withDrawAuditDto.getOrderNo());
            return Result.newSuccess();
        } catch (Exception e) {
            log.error("提现申请发生异常,事务回滚:{}", e);
            transactionManager.rollback(transactionStatus);
            return Result.newError(ResultCode.SAVE_DB_ERROR);
        }
    }

    private WithDrawOrderResultDto convertToDto(TbWithDrawInfo tbWithDrawInfo) {
        WithDrawOrderResultDto withDrawOrderResultDto=new WithDrawOrderResultDto();
        BeanUtils.copyProperties(tbWithDrawInfo,withDrawOrderResultDto);
        withDrawOrderResultDto.setApplyTime(DateUtil.getDateTimeFormat(tbWithDrawInfo.getApplyTime()));
        withDrawOrderResultDto.setStatusName(WithDrawStatusEnum.parse(tbWithDrawInfo.getStatus()).getName());
        withDrawOrderResultDto.setAuditTime(DateUtil.getDateTimeFormat(tbWithDrawInfo.getAuditTime()));
        return withDrawOrderResultDto;
    }

}

